/****************************************************************************/
/*
* xml object api.
*/
/****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/sem.h>
#include <errno.h>
#include <signal.h>

#include "cms_common.h"
#include "cms_log.h"
#include "libmdm.h"
#include "cms_mdm.h"

/*
	Description: 
		create parameter list.
	Parameters:
		NULL
	return:
		return parameter list head.
*/
paraValueSettingList_t *newParameterList(void)
{
	paraValueSettingList_t *paraListHead = NULL;

	paraListHead = (paraValueSettingList_t *)calloc(1, sizeof(paraValueSettingList_t));
	if(paraListHead == NULL){
		CMS_LOG(LL_ERROR,"malloc parameter list fail.\n");
		return NULL;
	}

	return paraListHead;
}


/*
	Description: 
		set parameter info to parameter list.
	Parameters:
		list -- parameter list.
		parameter -- parameter name.
		type -- parameter type.
		value -- parameter value.
	return:
		-1 -- fail
		0 -- success
*/
int setParameterToList(paraValueSettingList_t *list, const char *parameter, uint32_t type, void *value){
	paraValueSettingList_t *curPara = NULL;
	uint32_t valueType = type;
	uint32_t valueLen = 0;

	if(list == NULL){
		CMS_LOG(LL_ERROR," parameter list head is NULL.\n");
		return -1;
	}

	if(strlen(list->parameter) == 0){
		/*first parameter*/
		
		if(valueType == PARAMETER_TYPE_STRING){
			valueLen = strlen(value) + 1;
		}else{
			valueLen = (valueType & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS));
		}
		list->value = (uint8_t *)calloc(valueLen, sizeof(uint8_t));
		if(list->value == NULL){
			CMS_LOG(LL_ERROR, "calloc parameter list value fail.\n");
			return -1;
		}
		
		memcpy(list->value, value, valueLen);
		strcpy(list->parameter, parameter);
		list->type = type;
	}
	else{
		
		curPara = (paraValueSettingList_t *)calloc(1, sizeof(paraValueSettingList_t));
		if(curPara == NULL){
			CMS_LOG(LL_ERROR,"malloc parameter fail.\n");
			freeParameterList(list);
			return -1;
		}
		
		if(valueType == PARAMETER_TYPE_STRING){
			valueLen = strlen(value) + 1;
		}else{
			valueLen = (valueType & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS));
		}
		
		curPara->value = (uint8_t *)calloc(valueLen, sizeof(uint8_t));
		if(curPara->value == NULL){
			CMS_LOG(LL_ERROR, "calloc parameter list value fail.\n");
			free(curPara);
			freeParameterList(list);
			return -1;
		}
		
		memcpy(curPara->value, value, valueLen);
		strcpy(curPara->parameter, parameter);
		curPara->type = type;

		INSERT_NODE(list, curPara);
	}

	return 0;
}

/*
	Description: 
		free parameter list memory.
	Parameters:
		list -- parameter list.
	return:
		-1 -- fail
		0 -- success
*/
int freeParameterList(paraValueSettingList_t *list){
	paraValueSettingList_t *curPara = NULL, *tmpPara = NULL;
	
	if(list == NULL){
		CMS_LOG(LL_ERROR,"parameter list is NULL.\n");
		return 0;
	}

	curPara = list;
	while(curPara){
		tmpPara = curPara;
		curPara = curPara->next;

		free(tmpPara->value);
		tmpPara->value =  NULL;
		DELETE_NODE(list, tmpPara);
	}

	return 0;
}

cms_multiObjSettingList_t *newMultiObjList(void)
{
	cms_multiObjSettingList_t *pMultiObjListHead = NULL;

	pMultiObjListHead = (cms_multiObjSettingList_t *)calloc(1, sizeof(cms_multiObjSettingList_t));
	if(pMultiObjListHead == NULL){
		CMS_LOG(LL_ERROR,"malloc pMultiObjListHead list fail.\n");
		return NULL;
	}

	pMultiObjListHead->type = 0;

	return pMultiObjListHead;
}

int freeMultiObjList(cms_multiObjSettingList_t *list)
{
	cms_multiObjSettingList_t *curMultiObjList = list, *tmpMultiObjList = NULL;
	
	if(curMultiObjList == NULL){
		CMS_LOG(LL_ERROR,"multi obj list is NULL.\n");
		return 0;
	}

	while(curMultiObjList){
		tmpMultiObjList = curMultiObjList;
		curMultiObjList = curMultiObjList->next;

		if(tmpMultiObjList->paramList){
			freeParameterList(tmpMultiObjList->paramList);
		}
		DELETE_NODE(list, tmpMultiObjList);
	}

	return 0;
}

int addObjToListByName(cms_multiObjSettingList_t *pMultiObjList, char *objPath, obj_handle_type_t handleType)
{
	cms_multiObjSettingList_t *curList = pMultiObjList, *newCurList = NULL, *tmpList = NULL;
	
	if((curList !=  NULL) && (objPath != NULL) && (handleType >= OBJ_ADD && handleType <= OBJ_SET )){
		if(curList->type == 0){/*head*/
			curList->type = handleType;
			curList->objectInfo.isPathName = TRUE;
			strcpy(curList->objectInfo.object.pathName, objPath);	
		}else{
			newCurList = (cms_multiObjSettingList_t *)calloc(1, sizeof(cms_multiObjSettingList_t));
			if(newCurList == NULL){
				CMS_LOG(LL_ERROR,"malloc  new MultiObjListHead list fail.\n");
				return -1;
			}

			newCurList->type = handleType;
			newCurList->objectInfo.isPathName = TRUE;
			strcpy(newCurList->objectInfo.object.pathName, objPath);

			while(curList){/*found the last node of list*/
				tmpList = curList;
				curList = curList->next;
			}
			tmpList->next = newCurList;
			newCurList->next = NULL;
		}

		return 0;
	}

	return -1;
}

int addObjToListByOID(cms_multiObjSettingList_t *pMultiObjList, uint32_t OID, uint64_t OIA, obj_handle_type_t handleType)
{
	cms_multiObjSettingList_t *curList = pMultiObjList, *newCurList = NULL, *tmpList = NULL;
	
	if((curList !=  NULL)  && (handleType >= OBJ_ADD && handleType <= OBJ_SET )){
		if(curList->type == 0){/*head*/
			curList->type = handleType;
			curList->objectInfo.isPathName = FALSE;
			curList->objectInfo.object.objOID.OID = OID;
			curList->objectInfo.object.objOID.OIA = OIA;
		}else{
			newCurList = (cms_multiObjSettingList_t *)calloc(1, sizeof(cms_multiObjSettingList_t));
			if(newCurList == NULL){
				CMS_LOG(LL_ERROR,"malloc  new MultiObjListHead list fail.\n");
				return -1;
			}

			newCurList->type = handleType;
			newCurList->objectInfo.isPathName = FALSE;
			newCurList->objectInfo.object.objOID.OID = OID;
			newCurList->objectInfo.object.objOID.OIA = OIA;

			while(curList){/*found the last node of list*/
				tmpList = curList;
				curList = curList->next;
			}
			tmpList->next = newCurList;
			newCurList->next = NULL;
		}
		return 0;
	}

	return -1;
}

int setParamToMultiObjList(cms_multiObjSettingList_t *pMultiObjList, char *parameter, uint32_t type, void *value)
{
	cms_multiObjSettingList_t *curList = pMultiObjList, *tmpList = NULL;
	int ret = -1;
	
	if((curList != NULL) && (parameter != NULL) && (value != NULL)){
		while(curList){/*found the last node of list*/
			tmpList = curList;
			curList = curList->next;
		}
		
		if(tmpList->paramList == NULL){
			tmpList->paramList = newParameterList();
			if(tmpList->paramList == NULL){
				return -1;
			}
		}
		
		ret = setParameterToList(tmpList->paramList, parameter, type, value);

		return ret;
	}

	return -1;
}


/*
	Description: 
		create mutex when allloc xmlshmcb or init xmlshmcb.
	Parameters:
		list -- parameter list.
	return:
		NULL -- fail
		mutex ptr -- success
*/
cmsMutexPack_t *create_mutex_package(cmsXmlCb_t *xmlShmCb)
{
	int shmid = -1;
	void *shmAddr = NULL;
	cmsMutexPack_t *cmsMutex = NULL;
	pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
	pthread_mutexattr_t lock_attr;

	shmid = shmget((key_t)1234, sizeof(cmsMutexPack_t), 0666);
	if(shmid < 0){
		shmid = shmget((key_t)1234, sizeof(cmsMutexPack_t), IPC_CREAT | 0666);
		if(shmid < 0){
			CMS_LOG(LL_ERROR, "Create lock shm id %d fail.\n", shmid);
			return NULL;
		}else{
			CMS_LOG(LL_FLOOD, "Create lock shm id %d success.\n", shmid);

			xmlShmCb->lockShmId = shmid;
			shmAddr = shmat(shmid, NULL, SHM_R | SHM_W);
			if(shmAddr == (void *)-1){
				CMS_LOG(LL_ERROR, "lochShm shmat %d fail.\n", shmid);
				cmsMutex = NULL;
				xmlShmCb->lockShmAddr = NULL;
				return cmsMutex;
			}
			xmlShmCb->lockShmAddr = shmAddr;
				
			cmsMutex = (cmsMutexPack_t *)shmAddr;

			pthread_mutexattr_init(&lock_attr);
			pthread_mutexattr_setpshared(&lock_attr, PTHREAD_PROCESS_SHARED);
			pthread_mutexattr_setrobust(&lock_attr, PTHREAD_MUTEX_ROBUST);
			pthread_mutexattr_settype(&lock_attr, PTHREAD_MUTEX_RECURSIVE);
			pthread_mutex_init(&lock, &lock_attr);

			cmsMutex->lock = lock;
			cmsMutex->lock_attr = lock_attr;

		}
	}else{
		CMS_LOG(LL_FLOOD, "Get lock shm id %d success.\n", shmid);
		
		xmlShmCb->lockShmId = shmid;
		shmAddr = shmat(shmid, NULL, SHM_R | SHM_W);
		if(shmAddr == (void *)-1){
			CMS_LOG(LL_ERROR, "lochShm shmat %d fail.\n", shmid);
			cmsMutex = NULL;
			return cmsMutex;
		}
		
		cmsMutex = (cmsMutexPack_t *)shmAddr;
		xmlShmCb->lockShmAddr = shmAddr;

	}

	return cmsMutex;
}

/*
	Description: 
		destory mutex.
	Parameters:
		xmlShmCb -- xml shm control block.
	return:
		-1 -- fail
		0  -- success
*/
int destory_mutex_package(cmsXmlCb_t	*xmlShmCb){
	int ret = -1;
	
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlShmCb is NULL.\n");
		return ret;
	}
		
	ret = shmctl(xmlShmCb->lockShmId, IPC_RMID, NULL);

	return ret;
}

void cmsXml_lock(pthread_mutex_t *lock)
{
#ifdef XML_LOCK_SUPPORT
	if(pthread_mutex_lock(lock) == EOWNERDEAD)
		pthread_mutex_consistent(lock);
#endif
}

void cmsXml_unlock(pthread_mutex_t *lock)
{
#ifdef XML_LOCK_SUPPORT
	pthread_mutex_unlock(lock);
#endif
}

/*
	Description: 
		use to get the ptr's offset
	Parameters:
		xmlShmCb:	xml share memory control block
		ptr: 		the node pointer
	return:
		return ptr's offset
*/
cmsoffset_t cmsXmlGetPtrOffset(cmsXmlCb_t *xmlShmCb, void *ptr){
	cmsoffset_t offset;

	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlShmCb is NULL.\n");
		return 0;
	}

	if(ptr == NULL){
		CMS_LOG(LL_ERROR, "ptr is NULL.\n");
		return 0;
	}
	
	offset = (uintptr_t)ptr-(uintptr_t)xmlShmCb->baseaddr;

	return offset;
}

/*
	Description: 
		use to get the index child's total number
	Parameters:
		xmlShmCb:	xml shm control block
		id: the index child's offsetid
	return:
		-1: get object fail.
		0 : the object is not index child, have no child object.
		> 0: return child count.
*/
int cmsXml_getIndexChildCount(cmsXmlCb_t *xmlShmCb, cmsoffset_t id)
{
	void *object = NULL;

	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}
	
	object = cmsXml_getObjectByID(xmlShmCb, id);
	if(object == NULL){
		CMS_LOG(LL_FLOOD, "have no this object, %u\n", id);
		return -1;
	}
	if ((xmlShmCb->objectNode->attributes & ATTR_INDEXCHILD) != ATTR_INDEXCHILD){
		return 0;	/*the id is not index child*/
	}
	
	return xmlShmCb->objectNode->sibling.child_count;
}

/*
	Description: 
		use to get the index child's status
	Parameters:
		xmlShmCb:	xml shm control block
		id: the index child's id
	return:
		return INDEX_OBJECT_INACTIVE: inactive, INDEX_OBJECT_ACTIVE: active
		-1, get child status fail.
*/
int cmsXml_getIndexChildStatus(cmsXmlCb_t *xmlShmCb, cmsoffset_t id){
	void *object = NULL;

	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}
	
	object = cmsXml_getObjectByID(xmlShmCb, id);
	if(object == NULL)
		return -1;

	if ((xmlShmCb->objectNode->attributes & ATTR_NODECONFIGURED) != ATTR_NODECONFIGURED){
		return INDEX_OBJECT_INACTIVE;	/*node is not active*/
	}
	
	return INDEX_OBJECT_ACTIVE;
}


/*
	Description: 
		use to get the node's full path names
	Parameters:
		xmlShmCb:	xml shm control block
		id: the object node's id offset
	return:
		return a pointer point to the path
	note:
		after using, you MUST call rdmFreeFullPathBuffer() 
		to free the memory of full path
*/
char *cmsXml_getFullPathByID(cmsXmlCb_t *xmlShmCb, cmsoffset_t id){
	void *object;
	objectNode_t *node;
	char *nodeName, *path;
	int length = 1024, nodeLen = 0, firstNode = 1;
	int OID = 0, depth = 0;
	char tmpName[ BUFLEN_8 ] = { 0 };
	
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return NULL;
	}
	
	uint64_t targetIA = cmsXmlGetPreObjIA( xmlShmCb, id );

	depth = cmsXmlGetIADepth( targetIA );
	/* get the node from pre-obj. */
	node = cmsXmlGetObjRealAddr( xmlShmCb, cmsXmlGetPreObjNode( xmlShmCb, id ) );
	OID = cmsXml_GetOIDByOffset( xmlShmCb, node->object );
	object = cmsXml_getObjectByID( xmlShmCb, node->object );

	if (object == NULL){
		CMS_LOG(LL_ERROR, "get object by ID(OID:%d) fail\n", OID);
		cmsXml_SetCBData( xmlShmCb, 0 );
		return NULL;
	}
	node = xmlShmCb->objectNode;

	path = calloc(1, length);
	while(node){
		nodeName = cmsXmlGetObjRealAddr(xmlShmCb, node->name);

		//printf( "depth=%d, v=%d, strlen=%d, name=%s\n", depth, cmsXmlGetIAInfo( targetIA, depth ), strlen( nodeName ), nodeName );
		if ( depth && ( strlen( nodeName ) == 1 ) && ( *nodeName == 'i' ) )
		{
			memset( tmpName, 0, BUFLEN_8 );
			sprintf( tmpName, "%d", cmsXmlGetIAInfo( targetIA, depth ) );
			depth--;
			nodeName = tmpName;
		}

		nodeLen = strlen(nodeName);

		if (firstNode == 1){
			/*first node*/
			strcat(path, nodeName);
			firstNode = 0;
			length -= (nodeLen + 1);	/*1 for '\0'*/
		}
		else{
			if ((length - (nodeLen+1)) < 0){
				CMS_LOG(LL_ERROR, "memory for Full path too small\n");
				free(path);
				return NULL;
			}
			else{
				memmove(path+(nodeLen+1) , path, (1024 - length));	/*+1 is for '.'*/
				*(path+nodeLen) = '.';
				memcpy(path, nodeName, nodeLen);
			}
			length -= (nodeLen + 1);
		}
		node = cmsXmlGetObjRealAddr(xmlShmCb, node->parent);
	}

	CMS_LOG(LL_FLOOD, "full path:%s\n", path);
	cmsXml_SetCBData( xmlShmCb, id );


	return path;
}

/*
	Description: 
		Search and get an empty index child node
	Parameters:
		xmlShmCb:	xml shm control block
		node:	the middle index child node
	return:
		return index child node or NULL if all index child node is occupied
*/
objectNode_t *cmsXml_getIndexChild(cmsXmlCb_t *xmlShmCb, objectNode_t *node)
{
	objectNode_t *next, *current = NULL;
	char *ptr;
	int count;
	int i = 1;
	
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return NULL;
	}
	
	if (node == NULL){
		return NULL;
	}

	count = node->sibling.child_count;
	while (count > 0){
		next = node + i;
		if ((next->attributes & ATTR_NODECONFIGURED) != ATTR_NODECONFIGURED){
			current = next;
			break;
		}
		i++;
		count--;
	}			
	
	if (current){
		ptr = cmsXmlGetObjRealAddr(xmlShmCb, current->name);
		xmlShmCb->objectIndex = atoi(ptr);	
		return current;
	}
	return NULL;
}

/*
	Description: 
		this function is used to get the object node ptr, length of the object structure, and 
		the object id(object address at share memory)
	Parameters:
		xmlShmCb:	xml shm control block
			xmlShmCb->objectSize:	use to get object size
			xmlShmCb->index:	use to get the index number, if the name of node is an index node
			xmlShmCb->node:	object node ptr

		id:	the object id = object offset, 
		please refer to rdm_objectID.h, ex.#define igd.modules.dhcp.settings 0x80000000
		the id of igd.modules.dhcp.settings is 0x80000000

	return:
		return the object address, object address at share memory
	example:
		{
			cmsXmlCb_t *xmlShmCb= NULL;
			void *object;
			object = cmsXml_getObjectByProtoName(xmlShmCb, InternetGatewayDevice_DeviceInfo_VendorConfigFile_1);
		}		
*/
void *cmsXml_getObjectByID(cmsXmlCb_t *xmlShmCb, cmsoffset_t id){
	void *ptr;
	objectNode_t *child, *tmp;
	cmsoffset_t offset;

	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return NULL;
	}
	
	if(id >= X2S_MEMORY_SIZE){
		CMS_LOG(LL_ERROR, "object offset id(%d) is out of share memory range!!!\n", id);
		return NULL;
	}
	/*if the node is a index node, need to find the i node and return the i node object address and i*/
	/*use id to get node pointer*/
	/*get node's offset*/
	ptr = cmsXmlGetObjRealAddr(xmlShmCb, id - sizeof(cmsoffset_t)*2);	/*timestamp, node offset, meta offset*/
	//memcpy(&offset, ptr, sizeof(cmsoffset_t));
	
	offset = *((cmsoffset_t *)ptr);
	tmp = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, offset);
	if(tmp == NULL){
		CMS_LOG(LL_FLOOD, "no this object\n");
		return NULL;
	}
	if (tmp->attributes & ATTR_INDEXNODE){
		child = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, tmp->child);
		tmp = child;

		if (tmp == NULL){
			/*all index child is ocupied*/
			return NULL;
		}
	}
	xmlShmCb->objectSize = tmp->object_size & GET_OBJECT_SIZE_MASK ;
	xmlShmCb->objectNode = tmp;

	ptr = cmsXmlGetObjRealAddr(xmlShmCb, tmp->object);
	return ptr;
}

static int cmsXml_CheckChildStatus( cmsXmlCb_t *xmlShmCb, objectNode_t *node )
{

	int ret = 0;
	
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}
	
	if ((node->attributes & ATTR_INDEXCHILD) == ATTR_INDEXCHILD){
		/* just return configured if this node is indexchild. */
		return 1;

	}
	else{
			
		if (((node->attributes & ATTR_NODECONFIGURED) == ATTR_NODECONFIGURED)&&((node->attributes & ATTR_ALWAYSACTIVE) != ATTR_ALWAYSACTIVE)){
			ret = 1;
			return ret;
		}

		if(node->sibling.tree.prev){
			if ((ret = cmsXml_CheckChildStatus(xmlShmCb, cmsXmlGetObjRealAddr(xmlShmCb, node->sibling.tree.prev))) == 1){
				return ret;
			}
		}
		if(node->sibling.tree.next){
			if ((ret = cmsXml_CheckChildStatus(xmlShmCb, cmsXmlGetObjRealAddr(xmlShmCb, node->sibling.tree.next))) == 1){
				return ret;
			}
		}
	}
	return ret;
}


/*
	Description: 
		use to active/deactive index object node
	Parameters:
		xmlShmCb:	rdm control block
		objOff: the object offset
		active: active type
				#define INDEX_OBJECT_ACTIVE		1
				#define INDEX_OBJECT_DEACTIVE	0
	return:
		return CMS_OK
	call by:

*/
int cmsXml_setNodeStatus( cmsXmlCb_t *xmlShmCb, objectNode_t *node, int active )
{
	objectNode_t *parent = NULL, *child = NULL;
	int flag = 0;

	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}

	if (active == 1){	/*enable, called at cmsXml_SetIndexObject or cmsXml_SetParameter*/
#if !defined(SYSDEF_PARSER_ON_HOST)
		if ( xmlShmCb->IA )
		{
			/* set attribute to preobj. */
			cmsXml_SetPreObjStatus( xmlShmCb, xmlShmCb->offset, INDEX_OBJECT_ACTIVE );
		}
#endif
		parent = node;
		while (parent){
			parent->attributes |= ATTR_NODECONFIGURED;
			/*if node is index child, remove ATTR_NODECONFIGURED from i node*/

			parent = cmsXmlGetObjRealAddr(xmlShmCb, parent->parent);
		}
	}else{	/*disable*/
		/*check child's status*/

		/*if original's attr is NODECONFIGURED, check child's status*/
//		child = cmsXmlGetObjRealAddr(xmlShmCb, node->child);
		if ((node->attributes & ATTR_NODECONFIGURED) == ATTR_NODECONFIGURED){
			/*if one of the child is NODECONFIGURED, keep node's attr to NODECONFIGURED*/
//			flag = cmsXml_CheckChildStatus(xmlShmCb, child);
			/*otherwise, remove NODECONFIGURED from node's attr*/
//			if (flag == 0){
//				node->attributes &= ~ATTR_NODECONFIGURED;
				/*check parent's attr need to modify or not*/
//				parent = cmsXmlGetObjRealAddr(xmlShmCb, node->parent);
#if !defined(SYSDEF_PARSER_ON_HOST)
				if ( xmlShmCb->IA )
				{
					/* set attribute to preobj. */
					cmsXml_SetPreObjStatus( xmlShmCb, xmlShmCb->offset, INDEX_OBJECT_INACTIVE );
				}
#endif
				parent = node;
				while (parent){
					child = cmsXmlGetObjRealAddr(xmlShmCb, parent->child);
					if (child != NULL){
						flag = cmsXml_CheckChildStatus(xmlShmCb, child);
						if ((flag == 0)&&((parent->attributes & ATTR_OBJECTNODE) == ATTR_OBJECTNODE)){
							/*if the node is object node, check the own parameters are changed or not*/
#if !defined(SYSDEF_PARSER_ON_HOST)
							if ( xmlShmCb->IA )
							{
								flag = 1;
							}
							else
#endif
							flag = cmsXml_checkObjectChg(xmlShmCb, parent);
						}
					}
					else{
						flag = 0;
					}
					if ((flag == 0)&&((parent->attributes & ATTR_ALWAYSACTIVE) != ATTR_ALWAYSACTIVE)){
						parent->attributes &= ~ATTR_NODECONFIGURED;
					}

					parent = cmsXmlGetObjRealAddr(xmlShmCb, parent->parent);
				}				
//			}
			
		}
		/*otherwise, don't care*/
	}
	
	return CMS_OK;
}


int cmsXml_checkObjectChg(cmsXmlCb_t *xmlShmCb, objectNode_t *node){
	int ret = 0;
	uint16_t meta_count;
	char *meta_ptr;
	uint8_t meta_len = 0;
	cmsoffset_t attrOffset;
	uint32_t flags;
	void *object, *tmp = NULL;
	cmsoffset_t paraOffset;
	uint32_t type_size, size;

	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}
	
	object = cmsXmlGetObjRealAddr( xmlShmCb, xmlShmCb->offset );


	/*allocate config_size and default is 0*/
	tmp = calloc( 1, node->object_size & GET_OBJECT_SIZE_MASK );
	if (tmp == NULL){
		CMS_LOG(LL_ERROR, "memory is not enough!!\n");
		return ret;
	}
	meta_count = NTOHS(node->meta_count);
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(node->meta));
	while(meta_count){
		meta_len = *((uint8_t *)meta_ptr);
		if (meta_len != PADDING_META_LEN){
			/*find default parameter*/
			paraOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(cmsoffset_t)*2+sizeof(uint32_t)))));
 			attrOffset = *((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(uint32_t)+sizeof(cmsoffset_t))));
			flags = *((uint32_t *)(object + NTOHDL(attrOffset)));
			type_size = NTOHL(*((uint32_t *)(meta_ptr + meta_len - sizeof(uint32_t))));
			size = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);				
			if ((flags & PARAMETER_ATTR_DEFAULTVALUE) == PARAMETER_ATTR_DEFAULTVALUE){
				/*compare default*/
				if (memcmp((object+paraOffset), (object+paraOffset+size), size) != 0){
					ret = 1;
					break;
				}
			}
			else{
				/*compare with 0*/
				if (memcmp((object+paraOffset), (tmp+paraOffset), size) != 0){
					ret = 1;
					break;
				}				
			}
			size = sizeof(uint32_t);
			if ((flags & PARAMETER_ATTR_DEFAULTATTR) == PARAMETER_ATTR_DEFAULTATTR){
				/*compare default*/				
				if (memcmp((object+attrOffset), (object+attrOffset+size), size) != 0){
					ret = 1;
					break;
				}				
			}
			else{
				/*has been modified if has other attr except FIX BITS*/
				if ((flags & ~PARAMETER_ATTR_FIX_BITS) != 0){
					ret = 1;
					break;
				}	
			}
		}
		meta_ptr = meta_ptr + meta_len;
		meta_count--;
	}

	free(tmp);

	CMS_LOG(LL_FLOOD, "Parameter change check ret:%d!!\n", ret);
	return ret;
}


/*
	Description: 
		use to copy object value from node to node, including descendants
	Parameters:
		xmlShmCb:	xml shm control block
		src: src node
		dst: dst node
		flag: use to distinguish copy node to node or reset value from i node to other node
				#define COPY_OBJECT_VALUE		1
				#define RESET_INDEXCHILD_OBJECT_VALUE	0
	return:
		return CMS_OK
	call by:

*/
int cmsXml_copyObjectNodeToNode(cmsXmlCb_t *xmlShmCb, objectNode_t *src, objectNode_t *dst, int flag){
	void *object, *sobject;
	char *metaAddr, *meta_ptr, *name;
	cmsoffset_t metaOffset, paraOffset, attrOffset;
	uint16_t meta_count;
	uint8_t meta_len = 0;
	uint32_t type_size = 0;
	uint32_t attr = 0, child_count = 0, i;
	int size = 0;
	objectNode_t *snext, *dnext, *sprev, *dprev, *schild, *dchild;

	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}
	
	CMS_LOG(LL_FLOOD, "enter\n");
	if (dst->object_size == 0)
		goto check_child;

	sobject = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(src->object));
	object = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(dst->object));
	meta_count = NTOHS(dst->meta_count);
	//memcpy(object, sobject, node->object_size);
	memcpy(object, sobject, NTOHL(dst->config_size));
	metaAddr = sobject -sizeof(cmsoffset_t);
	metaOffset = *((cmsoffset_t *)metaAddr);
	meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(metaOffset));

	if (flag == RESET_INDEXCHILD_OBJECT_VALUE){
		if ((dst->attributes & ATTR_ALWAYSACTIVE) != ATTR_ALWAYSACTIVE){
			dst->attributes &= ~ATTR_NODECONFIGURED;
		}
	}
	else if (flag == COPY_OBJECT_VALUE){
		dst->attributes = src->attributes;
	}
	while(meta_count)
	{
		meta_len = *((uint8_t *)meta_ptr);
		if (meta_len != PADDING_META_LEN){
			type_size = NTOHL(*((uint32_t *)(meta_ptr + meta_len - sizeof(uint32_t))));
			paraOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(cmsoffset_t)*2+sizeof(uint32_t)))));
			attrOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(cmsoffset_t)*1+sizeof(uint32_t)))));
			attr = NTOHL(*((uint32_t *)(sobject+attrOffset)));
			if ((attr & PARAMETER_ATTR_CONFIG) != PARAMETER_ATTR_CONFIG){//Ex:interface name don't want user to modify, so its' value will be non-configure and read-only
					if ((attr & PARAMETER_ATTR_READONLY) != PARAMETER_ATTR_READONLY){
						size = (int)(type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS));
						memcpy((object+paraOffset), (sobject+paraOffset), size);
					}
			}
		}
		meta_ptr = meta_ptr + meta_len;
		meta_count--;
	}
check_child:	
	attr = NTOHL(dst->attributes);
	if ((attr & ATTR_INDEXCHILD) == ATTR_INDEXCHILD){
		name = cmsXmlGetObjRealAddr(xmlShmCb, NTOHL(dst->name));
		if (!strcmp(name, "i")){
			child_count = NTOHL(dst->sibling.child_count);
			i = 1;
			while (child_count > 0){
				cmsXml_copyObjectNodeToNode(xmlShmCb, src+i, dst+i, flag);
				child_count--;
				i++;
			}
		}
	}
	else{
		if (dst->sibling.tree.prev){
			dprev = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(dst->sibling.tree.prev));
			sprev = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(src->sibling.tree.prev));
			cmsXml_copyObjectNodeToNode(xmlShmCb, sprev, dprev, flag);
		}
		if (dst->sibling.tree.next){
			dnext = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(dst->sibling.tree.next));
			snext = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(src->sibling.tree.next));
			cmsXml_copyObjectNodeToNode(xmlShmCb, snext, dnext, flag);
		}		
	}
	
	if (dst->child){
		dchild = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(dst->child));
		schild = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(src->child));		
		cmsXml_copyObjectNodeToNode(xmlShmCb, schild, dchild, flag);
	}

	return 0;
}

/*
	Description: 
		Search object node
	Parameters:
		xmlShmCb:	xml shm control block
		node:	
		name:	the object path, ex. igd.modules.dhcp.settings.start
	return:
		return object node address
*/
static objectNode_t *cmsXml_SearchObjNodeByName(cmsXmlCb_t *xmlShmCb, objectNode_t *node, char *name)
{
	objectNode_t *child, *current = NULL;
	int last = 0;
//	char *token;
	uint32_t name_len = 0;

	if ((xmlShmCb == NULL)||(node == NULL)){
		CMS_LOG(LL_ERROR, "NULL fail\n");
		return NULL;
	}
	/*use strchr to replace strtok!!!!*/
//	token = strchr(name, ".");
//	if(!token)
//	{
//		last = 1;
//		token = name + strlen(name);
//	}

//	current = rdmSearchChildNode(node, name, token-name);
	
	current = cmsXml_SearchChildNode(xmlShmCb, node, name, &name_len);
	if (name_len & LAST_NAME_FOUND){
		last = 1;
		name_len &= ~LAST_NAME_FOUND;
	}
		
	if(current)
	{
		if(!last){
			current = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, current->child);
			return cmsXml_SearchObjNodeByName(xmlShmCb, current, name+name_len+1);
		}
		else{
			/*this is index node, find a empty index child node and give the index*/
			if (current->attributes & ATTR_INDEXNODE){
				child = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, current->child);
				/* we don't need to find an empty indexchild. just return indexchild node. */
				current = child;
			}
			if (current->attributes & ATTR_OBJECTNODE){
				return current;
			}
			else{
				/*find node, but this node is not a object node (node with parameters)*/
				CMS_LOG(LL_ERROR, "not a object node\n");
				return NULL;
			}
		}
	}
	CMS_LOG(LL_ERROR, "cannot find object %s\n", name);
	return NULL;
}

/*
	Description: 
		this function is used to get the object node ptr, length of the object structure, and 
		the object id(object address at share memory)
	Parameters:
		xmlShmCb:	xml shm control block
			xmlShmCb->objectSize:	use to get object size
			xmlShmCb->index:	use to get the index number, if the name of node is an index node
			xmlShmCb->node:	object node ptr		
		name:	the object name, ex. igd.modules.dhcp.settings.start

	return:
		return the object address, object address at share memory
	example:
		{
			cmsXmlCb_t *xmlShmCb= NULL;
			void *object;
			char *name = "InternetGatewayDevice.DeviceInfo.VendorConfigFile.1"
			object = cmsXml_getObjectByProtoName(xmlShmCb, name);
		}
*/
void *cmsXml_getObjectByProtoName( cmsXmlCb_t *xmlShmCb, char *name )
{
	objectNode_t *root = NULL, *tmp = NULL;

	if ( xmlShmCb == NULL )
	{
		CMS_LOG( LL_ERROR, "xmlShmCb == NULL\n");
		return NULL;
	}

	/*if the node is a index node, need to find the i node and return the i node object address and i*/
	root = xmlShmCb->rootNode;
	if ( ( tmp = cmsXml_SearchObjNodeByName( xmlShmCb, root, name ) ) == NULL )
	{
		CMS_LOG( LL_ERROR, "cmsXml_SearchObjNodeByName fail, search object name is %s\n", name);
		return NULL;
	}

	xmlShmCb->objectSize = tmp->object_size & GET_OBJECT_SIZE_MASK ;
	xmlShmCb->objectNode = tmp;

	return cmsXmlGetObjRealAddr( xmlShmCb, tmp->object );
}

/*______________________________________________________________________________
**	strnicmp
**
**	descriptions:
**
**	parameters:
	str1: node's name
	str2: object name, ex. aaa.bbb.ccc
	namelen: get the namelen of string at str2, ex. for aaa, namelen is 3.
**	local:
**	global:
**	return:
**	called by:
**	call:
**	revision:
**____________________________________________________________________________*/
int
strlenicmp(
    char *str1,
    char *str2, 
    uint32_t *namelen
)
{
    char ch1, ch2;
    int diff;
	int len = 0;
 
    if ( str1 == str2 ) {
        return 0;
    } else if ( str1 == NULL ) {
        return -1;
    } else if ( str2 == NULL ) {
        return 1;
    }

 	while ((*str2 == '0')||(*str2 == ' ')){
		len++;
		str2++;
	}
    while ( 1 ) {
        diff = (ch1 = *str1) - (ch2 = *str2);
        if ( diff < 0 ) {
            if ( (diff != ('A'-'a')) || (ch1 < 'A') || (ch1 > 'Z')) { 
                /* found difference */
				if ((ch1 == '\0') && (ch2 == '.')){
					/*found difference, but two strings are the same*/
					if (namelen != NULL){
						*namelen = len;
					}					
					break;
				}			
                return -1;
            } 
            /* else matched with different letter case -> continue */
        } else if ( diff > 0 ) {
            if ( (diff != ('a'-'A')) || (ch1 < 'a') || (ch1 > 'z') ) {
                /* found difference */
                return 1;
            }
            /* else matched with different letter case -> continue */
        } else if (( ch1 == '\0' )) {
            /* end of str1 && end of str2 */
			/*should happen at last string!*/
			if (namelen != NULL){
				*namelen = len;
				*namelen |= LAST_NAME_FOUND;
			}				
            break;
        } 
        /* else matched exactly -> continue */
		len++;
        str1++;
        str2++;
    }


    return 0;
} 


/*
	Description: 
		Search object node
	Parameters:
		xmlShmCb:	xml shm control block
		node:	object node's middle
		name:	the child node's name
		namelen: use to get the child node's name length
	return:
		return the object node's ptr or NULL
*/
objectNode_t *cmsXml_SearchChildNode( cmsXmlCb_t *xmlShmCb, objectNode_t *node, char *name, uint32_t *namelen)
{
	int retcode = 0;
	objectNode_t *current;
	char *namePtr;
	int count = 0, i = 0;
	
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return NULL;
	}
	//CMS_LOG(LL_FLOOD, "%s(): enter name:%s\n", __FUNCTION__, name);/*wxT, comment it for memory leak*/
	if (node == NULL){
		return NULL;
	}
	current = node;

	/*check index child first, if the node is index child, don't use AVL tree search*/
	if (((node->attributes) & ATTR_INDEXCHILD) == ATTR_INDEXCHILD){
		count = (node->sibling.child_count);
		while (count >= 0){
			current = node + i;
			namePtr = cmsXmlGetObjRealAddr(xmlShmCb, (current->name));
			if (strlenicmp(namePtr, name, namelen) == 0){
				return current;
			}else if(strcmp(namePtr,"i") == 0){
					return NULL;
			}
			i++;
			count--;
		}
		return NULL;		
	}

	/*AVL tree search*/
	while(current){
		namePtr = cmsXmlGetObjRealAddr(xmlShmCb, (current->name));
//		len = node->name_len;
//		if (namelen > len)
//			len = namelen;
		if(namePtr!=NULL)
			retcode = strlenicmp(namePtr, name, namelen);
		if (retcode == 0){
			return current;
		}
		else if (retcode > 0){
			current = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, (current->sibling.tree.next));	/*smaller*/
		}
		else{
			current = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, (current->sibling.tree.prev));	/*larger*/
		}
	}
	return NULL;
}

/*
	Description: 
		use to active/deactive index object node
	Parameters:
		xmlShmCb:	xml shm control block
		objOff: the object offset
		active: active type
				#define INDEX_OBJECT_ACTIVE		1
				#define INDEX_OBJECT_DEACTIVE	0
	return:
		return CMS_OK
	call by:

*/
int cmsXml_setIndexObject(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOff, int active)
{
	cmsoffset_t nodeOffset;
	char *nodeAddr = NULL;
	objectNode_t *node = NULL;
	void *object = NULL;
	//uint16_t meta_count;
#if !defined(SYSDEF_PARSER_ON_HOST)
#else
	int count = 0;
	char *name = NULL;
	objectNode_t *inode = NULL;
#endif
	int paramCount = 0;

	CMS_LOG(LL_FLOOD, "enter\n");
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}
	object = cmsXmlGetObjRealAddr(xmlShmCb, objOff);
	
	/*use oid to find the object node*/
	nodeAddr = object -sizeof(cmsoffset_t)*2;
	nodeOffset = *((cmsoffset_t *)nodeAddr);
	node = (objectNode_t *)cmsXmlGetObjRealAddr(xmlShmCb, nodeOffset);
	paramCount = NTOHS(node->meta_count);
	printf("current object has %d parameters.\n", paramCount);
	switch( active ){
		case INDEX_OBJECT_ACTIVE:	
			node->attributes |= ATTR_NODECONFIGURED;
			cmsXml_setNodeStatus(xmlShmCb, node, 1);
#if !defined(SYSDEF_PARSER_ON_HOST)
			cmsXml_SetPreObjStatus( xmlShmCb, objOff, 1 );
#endif
			break;
		case INDEX_OBJECT_INACTIVE:
#if !defined(SYSDEF_PARSER_ON_HOST)
			cmsXml_SetPreObjStatus( xmlShmCb, objOff, 0 );
#else
			if ((node->attributes & ATTR_ALWAYSACTIVE) != ATTR_ALWAYSACTIVE){
				node->attributes &= ~ATTR_NODECONFIGURED;
			}
			/*copy the default value back to the index child*/
			if (node->attributes & ATTR_INDEXCHILD){
				/*leaf child use name to find i node*/
				name = cmsXmlGetObjRealAddr(xmlShmCb, node->name);
				if (*name == 'i'){
					CMS_LOG(LL_ERROR, "error, should not set i node\n");
				}
				else{
					count = atoi(name);
					inode = node - count;
					/*copy default value from i node and its child node*/
					cmsXml_copyObjectNodeToNode(xmlShmCb, inode, node, RESET_INDEXCHILD_OBJECT_VALUE);
				}
			}
#endif
			break;
		case INDEX_OBJECT_INACTIVE_NORESET:
			if ((node->attributes & ATTR_ALWAYSACTIVE) != ATTR_ALWAYSACTIVE){
				node->attributes &= ~ATTR_NODECONFIGURED;
			}
			break;	
		default:
			break;
	}
	return CMS_OK;
}


void * cmsXml_addObjectByOIDIA(cmsXmlCb_t *xmlShmCb, uint32_t OID, uint64_t objIA, int count, char **parameter)
{
	CMS_LOG(LL_FLOOD, "Extrance\n");
	void *ptr = NULL;
	cmsoffset_t objOff;
#ifdef DBUS_OBJECT_NOTIFY
	cmsBoolean isNeedNotfiy = cmsXml_checkobjNeedNotify(xmlShmCb, OID);
	char objInfo[EVENT_CONTENT_MAX] = {0};
	//int sendFlag = 0;
	//int i = 0;
#endif

	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return NULL;
	}
	
	if(xmlShmCb->readOnly == 1){
		CMS_LOG(LL_ERROR, "current app authority of xml share memory is read only, can't use direct set api, please use right API!!!\n");
		return NULL;
	}
	
	ptr = cmsXml_GetObjectByOID(xmlShmCb, OID, objIA, ADD_IF_NOT_EXISTED);
#ifdef DBUS_OBJECT_NOTIFY
#ifdef GC_APPS_CTC
	if((xmlShmCb->srcFromDbus == FALSE)&&(isNeedNotfiy == TRUE) && (ptr != NULL))
#else
	if((isNeedNotfiy == TRUE) && (ptr != NULL))
#endif
	{
		sprintf(objInfo, "%u;%ju;%d;NULL", OID, objIA, CMS_OBJ_ADD);
		cms_eventNotify(CMS_EVENT_OBJ_NOTIFY_DBUS, PARAMETER_TYPE_STRING, objInfo);
	}
#endif

	objOff = cmsXmlGetPtrOffset(xmlShmCb, ptr);
	
	if(count > 0)
		cmsXml_setParameter(xmlShmCb, objOff, count, parameter);

#if 0//def DBUS_OBJECT_NOTIFY
	if((xmlShmCb->srcFromDbus == FALSE)&&(isNeedNotfiy == TRUE) && (count > 0)){
		for(i = 0; i < count; i+= 3){			
			if(sendFlag == 0){
				memset(objInfo, 0, EVENT_CONTENT_MAX);
				sprintf(objInfo, "%u;%ju;%d", OID, objIA, CMS_OBJ_SET);
				sendFlag = 1;
			}
			
			if((strlen(objInfo) + strlen(*(parameter+i))) >= EVENT_CONTENT_MAX){
				cms_eventNotify(CMS_EVENT_OBJ_NOTIFY_DBUS, PARAMETER_TYPE_STRING, objInfo);
				memset(objInfo, 0, EVENT_CONTENT_MAX);
				sprintf(objInfo, "%u;%ju;%d;%s", OID, objIA, CMS_OBJ_SET, *(parameter+i));
			}else
				sprintf(objInfo+strlen(objInfo), ";%s", *(parameter+i));
		}

		if(sendFlag == 1){
			cms_eventNotify(CMS_EVENT_OBJ_NOTIFY_DBUS, PARAMETER_TYPE_STRING, objInfo);
		}
	}
#endif


	CMS_LOG(LL_FLOOD, "Exit\n");
	return ptr;
}

void *cmsXml_addObjectByOIDWithParaList(cmsXmlCb_t *xmlShmCb, uint32_t OID, uint64_t objIA, paraValueSettingList_t *paraList)
{
	CMS_LOG(LL_FLOOD, "Extrance\n");
	void *objPtr = NULL;
	paraValueSettingList_t *curPara = NULL;
	setParaValue_t *setPtr, *tmpPtr;
	int paraCnt = 0;

	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return NULL;
	}

	if(xmlShmCb->readOnly == 1){
		CMS_LOG(LL_ERROR, "current app authority of xml share memory is read only, can't use direct set api, please use right API!!!\n");
		return NULL;
	}
	
	curPara = paraList;
	while(curPara){

		paraCnt++;
		curPara = curPara->next;
	}

	tmpPtr = setPtr = malloc(sizeof(setParaValue_t)*paraCnt);

	curPara = paraList;
	while(curPara){

		setPtr->parameter = curPara->parameter;
		setPtr->type = &(curPara->type);
		setPtr->value = curPara->value;
		setPtr++;
		
		curPara = curPara->next;
	}

	 objPtr = cmsXml_addObjectByOIDIA(xmlShmCb, OID, objIA, paraCnt, (char **)tmpPtr);
	 free(tmpPtr);

	 CMS_LOG(LL_FLOOD, "Exit\n");
	return objPtr;
}

void *cmsXml_addObjectByPathName(cmsXmlCb_t *xmlShmCb, char *pathName, int count, char **parameter)
{
	void *ptr = NULL;
	cmsoffset_t objOff;
#ifdef DBUS_OBJECT_NOTIFY
	cmsBoolean isNeedNotfiy = FALSE;
	char objInfo[EVENT_CONTENT_MAX] = {0};
	uint32_t objID = 0;
	uint64_t objIA = 0;
	//int sendFlag = 0;
	//int ret = CMS_NOK;
	//int i = 0;
#endif
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return NULL;
	}

	if(xmlShmCb->readOnly == 1){
		CMS_LOG(LL_ERROR, "current app authority of xml share memory is read only, can't use direct set api, please use right API!!!\n");
		return NULL;
	}

#ifdef DBUS_OBJECT_NOTIFY
	objectList_t *objList = cmsXml_GetObjListByName(xmlShmCb, pathName);
	if (objList != NULL){
		objID = objList->OID;
		objIA = objList->IA;
	}else{
		return NULL;
	}

	isNeedNotfiy = cmsXml_checkobjNeedNotify(xmlShmCb, objID);
#endif

	ptr = cmsXml_GetObjectByName(xmlShmCb, pathName, ADD_IF_NOT_EXISTED);
#ifdef DBUS_OBJECT_NOTIFY
#ifdef GC_APPS_CTC
	if((xmlShmCb->srcFromDbus == FALSE)&&(isNeedNotfiy == TRUE) && (ptr != NULL))
#else
	if((isNeedNotfiy == TRUE) && (ptr != NULL))
#endif
	{
		sprintf(objInfo, "%u;%ju;%d;NULL", objID, objIA, CMS_OBJ_ADD);
		cms_eventNotify(CMS_EVENT_OBJ_NOTIFY_DBUS, PARAMETER_TYPE_STRING, objInfo);
	}
#endif

	objOff = cmsXmlGetPtrOffset(xmlShmCb, ptr);
	
	if(count > 0)
		cmsXml_setParameter(xmlShmCb,  objOff, count, parameter);

#if 0 //def DBUS_OBJECT_NOTIFY
	if((xmlShmCb->srcFromDbus == FALSE)&&(isNeedNotfiy == TRUE) && (count > 0)){
		for(i = 0; i < count; i+= 3){			
			if(sendFlag == 0){
				memset(objInfo, 0, EVENT_CONTENT_MAX);
				sprintf(objInfo, "%u;%ju;%d", objID, objIA, CMS_OBJ_SET);
				sendFlag = 1;
			}
			
			if((strlen(objInfo) + strlen(*(parameter+i))) >= EVENT_CONTENT_MAX){
				cms_eventNotify(CMS_EVENT_OBJ_NOTIFY_DBUS, PARAMETER_TYPE_STRING, objInfo);
				memset(objInfo, 0, EVENT_CONTENT_MAX);
				sprintf(objInfo, "%u;%ju;%d;%s", objID, objIA, CMS_OBJ_SET, *(parameter+i));
			}else
				sprintf(objInfo+strlen(objInfo), ";%s", *(parameter+i));
		}

		if(sendFlag == 1){
			cms_eventNotify(CMS_EVENT_OBJ_NOTIFY_DBUS, PARAMETER_TYPE_STRING, objInfo);
		}
	}
#endif	
	return ptr;
}

void *cmsXml_addObjectByPathNameWithList(cmsXmlCb_t *xmlShmCb, char *pathName, paraValueSettingList_t *paraList)
{
	CMS_LOG(LL_FLOOD, "Extrance\n");
	void *objPtr = NULL;
	paraValueSettingList_t *curPara = NULL;
	setParaValue_t *setPtr, *tmpPtr;
	int paraCnt = 0;

	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return NULL;
	}

	if(xmlShmCb->readOnly == 1){
		CMS_LOG(LL_ERROR, "current app authority of xml share memory is read only, can't use direct set api, please use right API!!!\n");
		return NULL;
	}

	curPara = paraList;
	while(curPara){

		paraCnt++;
		curPara = curPara->next;
	}

	tmpPtr = setPtr = malloc(sizeof(setParaValue_t)*paraCnt);

	curPara = paraList;
	while(curPara){

		setPtr->parameter = curPara->parameter;
		setPtr->type = &(curPara->type);
		setPtr->value = curPara->value;
		setPtr++;
		
		curPara = curPara->next;
	}

	 objPtr = cmsXml_addObjectByPathName(xmlShmCb, pathName, paraCnt, (char **)tmpPtr);
	 free(tmpPtr);

	 CMS_LOG(LL_FLOOD, "Exit\n");
	return objPtr;
}


/*
	Description: 
		del xml object in shm by object OID & IA.
	Parameters:
		xmlShmCb -- share memory control block. 
		OID 	 -- object id.
		objIA 	 -- object instance array.
	return:
		CMS_NOK -- fail 										
		CMS_OK	-- success	
*/
int cmsXml_delObjectByOIDIA(cmsXmlCb_t *xmlShmCb, int OID, uint64_t objIA)
{
	int ret = -1;

	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}

	if(xmlShmCb->readOnly == 1){
		CMS_LOG(LL_ERROR, "current app authority of xml share memory is read only, can't use direct set api, please use right API!!!\n");
		return CMS_NOK;
	}
	
#ifdef DBUS_OBJECT_NOTIFY
	cmsBoolean isNeedNotfiy = cmsXml_checkobjNeedNotify(xmlShmCb, OID);
	char objInfo[EVENT_CONTENT_MAX] = {0};
	objectList_t *objChildList = NULL;
	
	if(cmsXmlGetObjectByOID(xmlShmCb, OID, objIA) != NULL)
		objChildList = cmsXml_GetFullChildList(xmlShmCb, OID, objIA);
#endif

	ret = cmsXml_DelObjectByOID(xmlShmCb, OID, objIA);
#ifdef DBUS_OBJECT_NOTIFY
#ifdef GC_APPS_CTC
	if((xmlShmCb->srcFromDbus == FALSE)&&(isNeedNotfiy == TRUE) && (ret == CMS_OK))
#else
	if((isNeedNotfiy == TRUE) && (ret == CMS_OK))
#endif
	{
		sprintf(objInfo, "%u;%ju;%d;NULL", OID, objIA, CMS_OBJ_DEL);
		cms_eventNotify(CMS_EVENT_OBJ_NOTIFY_DBUS, PARAMETER_TYPE_STRING, objInfo);

		/*send out the child object in dbus subscribe list*/
		while(objChildList){
			isNeedNotfiy = cmsXml_checkobjNeedNotify(xmlShmCb, objChildList->OID);
			if(isNeedNotfiy == TRUE){
				memset(objInfo, 0, sizeof(objInfo));
				sprintf(objInfo, "%u;%ju;%d;NULL", objChildList->OID, objChildList->IA, CMS_OBJ_DEL);
				cms_eventNotify(CMS_EVENT_OBJ_NOTIFY_DBUS, PARAMETER_TYPE_STRING, objInfo);
			}
			objChildList = objChildList->next;
		}
	}
	if(objChildList)
		cmsXml_FreeObjList(&objChildList);
#endif

	return ret;
}


/*
	Description: 
		del xml object in shm by object full path name.
	Parameters:
		xmlShmCb -- share memory control block.	
 		pathNmae --  object full path name.
	return:
		CMS_NOK -- fail											
		CMS_OK  -- success	
*/
int cmsXml_delObjectByPathName(cmsXmlCb_t *xmlShmCb, char *pathName)

{
	int ret = -1;
#ifdef DBUS_OBJECT_NOTIFY
	cmsBoolean isNeedNotfiy = FALSE;
	char objInfo[EVENT_CONTENT_MAX] = {0};
	uint32_t objID = 0;
	uint64_t objIA = 0;
#endif

	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}

	if(xmlShmCb->readOnly == 1){
		CMS_LOG(LL_ERROR, "current app authority of xml share memory is read only, can't use direct set api, please use right API!!!\n");
		return CMS_NOK;
	}

#ifdef DBUS_OBJECT_NOTIFY
	objectList_t *objList = cmsXml_GetObjListByName(xmlShmCb, pathName);
	if (objList != NULL){
		objID = objList->OID;
		objIA = objList->IA;
	}else{
		return CMS_NOK;
	}

	isNeedNotfiy = cmsXml_checkobjNeedNotify(xmlShmCb, objID);
	objectList_t *objChildList = NULL;
	
	if(cmsXmlGetObjectByOID(xmlShmCb, objID, objIA) != NULL)
		objChildList = cmsXml_GetFullChildList(xmlShmCb, objID, objIA);
#endif

	
	ret = cmsXml_DelObjectByName(xmlShmCb, pathName);
#ifdef DBUS_OBJECT_NOTIFY
#ifdef GC_APPS_CTC
	if((xmlShmCb->srcFromDbus == FALSE)&&(isNeedNotfiy == TRUE) && (ret == CMS_OK))
#else
	if((isNeedNotfiy == TRUE) && (ret == CMS_OK))
#endif
	{
		sprintf(objInfo, "%u;%ju;%d;NULL", objID, objIA, CMS_OBJ_DEL);
		cms_eventNotify(CMS_EVENT_OBJ_NOTIFY_DBUS, PARAMETER_TYPE_STRING, objInfo);

		/*send out the child object in dbus subscribe list*/
		while(objChildList){
			isNeedNotfiy = cmsXml_checkobjNeedNotify(xmlShmCb, objChildList->OID);
			if(isNeedNotfiy == TRUE){
				memset(objInfo, 0, sizeof(objInfo));
				sprintf(objInfo, "%u;%ju;%d;NULL", objChildList->OID, objChildList->IA, CMS_OBJ_DEL);
				cms_eventNotify(CMS_EVENT_OBJ_NOTIFY_DBUS, PARAMETER_TYPE_STRING, objInfo);
			}
			objChildList = objChildList->next;
		}
	}
	if(objChildList)
		cmsXml_FreeObjList(&objChildList);
#endif

	
	return ret;
}

int cmsXml_objectRestore(cmsXmlCb_t *xmlShmCb, cmsoffset_t objOffset)
{
	objectNode_t *srcNode = NULL;
	int objID = 0;
	cmsoffset_t srcObjOff = 0;
	uint16_t meta_count;
	char *meta_ptr;
	uint8_t meta_len = 0;
	cmsoffset_t attrOffset;
	uint32_t flags;
	void *object = NULL;
	cmsoffset_t paraOffset;
	uint32_t type_size, size;
	
	if(xmlShmCb == NULL){
		CMS_LOG(LL_ERROR, "xmlshmcb is NULL\n");
		return CMS_NOK;
	}

	if(xmlShmCb->readOnly == 1){
		CMS_LOG(LL_ERROR, "current app authority of xml share memory is read only, can't use direct set api, please use right API!!!\n");
		return CMS_NOK;
	}

	XML_LOCK(&xmlShmCb->cmsMutex->lock);
	objID = cmsXml_GetOIDByOffset(xmlShmCb, objOffset);
	if(objID == -1){
		CMS_LOG(LL_ERROR, "get obj id by offset fail!!!\n");
		XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
		return -1;
	}

	srcObjOff = cmsXml_GetOffsetByOID(objID);
	srcNode = (objectNode_t *)cmsXmlGetObjRealAddr( xmlShmCb, cmsXmlGetPreObjNode( xmlShmCb, srcObjOff ) );
	if ( srcNode == NULL )
	{
		CMS_LOG( LL_ERROR, "no this OID=%d.\n", objID);
		XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
		return -1;
	}

	if(srcNode->attributes & ATTR_INDEXNODE){
		CMS_LOG( LL_ERROR, "No need to reset index node object( OID=%d).\n", objID);
		XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
		return -1;
	}

	if(srcNode->attributes & ATTR_INDEXCHILD){
		cmsXml_SetObjDefault(xmlShmCb, objOffset, OBJECT_RESTORE_DATA);
	}else{//object node
		object = cmsXmlGetObjRealAddr( xmlShmCb, objOffset);
		meta_count = NTOHS(srcNode->meta_count);
		meta_ptr = cmsXmlGetObjRealAddr(xmlShmCb, NTOHDL(srcNode->meta));
		while(meta_count){
			meta_len = *((uint8_t *)meta_ptr);
			if (meta_len != PADDING_META_LEN){
				paraOffset = NTOHDL(*((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(cmsoffset_t)*2+sizeof(uint32_t)))));
	 			attrOffset = *((cmsoffset_t *)(meta_ptr + meta_len - (sizeof(uint32_t)+sizeof(cmsoffset_t))));
				flags = *((uint32_t *)(object + NTOHDL(attrOffset)));
				type_size = NTOHL(*((uint32_t *)(meta_ptr + meta_len - sizeof(uint32_t))));
				size = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);				
				if ((flags & PARAMETER_ATTR_DEFAULTVALUE) == PARAMETER_ATTR_DEFAULTVALUE){
					/*_default exist*/
					size = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
					/*restore value*/
					memcpy((object+paraOffset), (object+paraOffset+size), size);
				}
				else{
					/*_default non-exist*/
					size = type_size & ~((uint32_t)PARAMETER_TYPE_CLASS_BITS);
					memset((object+paraOffset), 0, size);
				}
			}
			meta_ptr = meta_ptr + meta_len;
			meta_count--;
		}
	}

	XML_UNLOCK(&xmlShmCb->cmsMutex->lock);
	return 0;
}

